package com.example.learn_spring_boot3.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.learn_spring_boot3.exception.ServiceException;
import com.example.learn_spring_boot3.mapper.UserMapper;
import com.example.learn_spring_boot3.service.UserService;
import com.example.learn_spring_boot3.utils.JWTUtils;
import com.example.learn_spring_boot3.utils.ResponseData;
import com.example.learn_spring_boot3.entity.User;
import io.jsonwebtoken.Claims;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserMapper userMapper;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public ResponseEntity<ResponseData> register(User user) {
        // 以用户名作为唯一标识
        if (user.getName() == null) {
            throw new ServiceException(403, "用户名不能为空");
        }

        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("name", user.getName());

        User selectOne = userMapper.selectOne(userQueryWrapper);

        if (selectOne == null) {
            // TODO 其它参数校验
            // 默认密码六个0
            user.setPassword("000000");
            int insert = userMapper.insert(user);
            if (insert > 0) {
                return ResponseEntity.ok(ResponseData.success(user));
            } else {
                throw new ServiceException(403, "用户注册失败");
            }
        } else {
            throw new ServiceException(403, "已存在相同的用户");
        }
    }

    @Override
    public ResponseEntity<ResponseData> login(String name, String password) {

        if (name == null || password == null) {
            throw new ServiceException(403, "用户名或密码不能为空");
        }

        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("name", name).eq("password", password);

        User user = userMapper.selectOne(userQueryWrapper);
        if (user == null) {
            throw new ServiceException(403, "用户名或密码错误");
        } else {
            // token 保存的参数
            HashMap<String, Object> map = new HashMap<>();
            map.put("userId", user.getId());
            map.put("timestamp", new Date().getTime());
            // 生成token
            String token = JWTUtils.generateToken(map);

            return ResponseEntity.ok(ResponseData.success(token));
        }
    }

    @Override
    public ResponseEntity<ResponseData> info(String token) {
        if (token == null) {
            throw new ServiceException(401, "权限不足");
        }

        try {
            Claims claims = JWTUtils.getClaimsFromToken(token);
            System.out.println("claims = " + claims);

            // 获取单个载荷, 对应 setSubject(xxx) 设置的
            // String userName = claims.getSubject();

            // 获取多个载荷, 对应 setClaims(xxx) 设置的
            Integer userId = claims.get("userId", Integer.class);
            // 去数据库中查询是否有该用户的信息
            User user = userMapper.selectById(userId);

            if (user == null) {
                throw new ServiceException(401, "用户不存在, 请重新登录");
            } else {
                return ResponseEntity.ok(ResponseData.success(user));
            }
        } catch (Exception err) {
            err.printStackTrace();
            throw new ServiceException(401, "权限不足");
        }
    }


    @Override
    public ResponseEntity<ResponseData> getList() {
        // QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        // sex=1 并且 age > 18
        // userQueryWrapper.eq("sex", 1).gt("age", 18);
        // List<User> users = userMapper.selectList(userQueryWrapper);

        List<User> users = userMapper.selectList(null);
        ResponseData<Object> success = ResponseData.success(users);
        return ResponseEntity.ok(success);
    }

    @Override
    public ResponseEntity<ResponseData> getListByPage(Integer current, Integer size) {
        Page<User> page = new Page<>(current, size);
        Page<User> userPage = userMapper.selectPage(page, null);
        ResponseData<Object> success = ResponseData.success(userPage);
        return ResponseEntity.ok(success);
    }

    @Override
    public ResponseEntity<ResponseData> getListByQuery(Integer sex, Integer age) {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        // SELECT id,name,age,sex FROM user WHERE ((sex = ? AND age = ?))
        // userQueryWrapper.and(i -> i.eq("sex", sex).eq("age", age))

        // SELECT id,name,age,sex FROM user WHERE ((sex = ?) OR (age = ?))
        userQueryWrapper.or(i -> i.eq("sex", sex))
                .or(i -> i.eq("age", age));
        List<User> users = userMapper.selectList(userQueryWrapper);
        ResponseData<Object> success = ResponseData.success(users);
        return ResponseEntity.ok(success);
    }

    @Override
    public ResponseEntity<ResponseData> getListAndOrders() {
        List<User> users = userMapper.selectAllUserAndOrders();
        ResponseData<Object> success = ResponseData.success(users);
        return ResponseEntity.ok(success);
    }

    @Override
    public ResponseEntity<ResponseData> getListByCatch() {
        String key = "getListByCatch";
        List<Object> catchList = redisTemplate.opsForList().range(key, 0, -1);
        ResponseData<Object> success = ResponseData.success(null);
        if (catchList != null && catchList.size() > 0) {
            System.out.println("获取redis缓存的用户数据");
            success.setData(catchList);
        } else {
            List<User> users = userMapper.selectList(null);
            success.setData(users);
            redisTemplate.opsForList().rightPush(key, users);
            System.out.println("设置redis缓存的用户数据");
        }
        return ResponseEntity.ok(success);
    }

    @Override
    public ResponseEntity<ResponseData> addTestData(int num) {

        if (num <= 0) {
            return ResponseEntity.ok(ResponseData.error(403, "不能添加小于0的数据", null));
        }

        ArrayList<User> users = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            User user = new User();
            int i1 = i + 1;
            user.setName("批量新增的用户" + i1);
            user.setAge(i1);
            user.setSex(i / 2 == 0 ? 0 : 1);
            user.setPassword("000000");
            users.add(user);
        }
        userMapper.addBatch(users);
        return ResponseEntity.ok(ResponseData.success(null));
    }

    @Override
    public ResponseEntity<ResponseData> getUserById(int id) {
        User user = userMapper.selectById(id);
        ResponseData<Object> success = ResponseData.success(user);
        return ResponseEntity.ok(success);
    }

    @Override
    public ResponseEntity<ResponseData> add(User user) {
        int i = userMapper.insert(user);
        if (i > 0) {
            // 重新查询插入的用户数据
            User insertUser = userMapper.selectById(user.getId());
            ResponseData<Object> success = ResponseData.success(insertUser);
            return ResponseEntity.ok(success);
        } else {
            return ResponseEntity.ok(ResponseData.error(413, "插入失败", null));
        }
    }

    @Override
    public ResponseEntity<ResponseData> addBatch(ArrayList<User> userList) {
        int i = userMapper.addBatch(userList);
        System.out.println("批量插入数据条数: " + i);

        // 获取需要返回的数据
        List<User> resultList = userList.stream()
                .map(User::getId)
                .map(userMapper::selectById)
                .collect(Collectors.toList());

        ResponseData<Object> success = ResponseData.success(resultList);
        return ResponseEntity.ok(success);
    }


    @Override
    public ResponseEntity<ResponseData> update(User user) {
        if (user.getId() != null) {
            // 更新操作
            int i = userMapper.updateById(user);
            if (i > 0) {
                ResponseData<Object> success = ResponseData.success(user);
                return ResponseEntity.ok(success);
            } else {
                return ResponseEntity.ok(ResponseData.error(413, "更新失败, id不存在", null));
            }
        } else {
            // 新增操作
            return this.add(user);
        }

    }

    @Override
    public ResponseEntity<ResponseData> delete(int id) {
        int i = userMapper.deleteById(id);
        if (i > 0) {
            ResponseData<Object> success = ResponseData.success(null);
            return ResponseEntity.ok(success);
        } else {
            return ResponseEntity.ok(ResponseData.error(413, "删除失败, id不存在", null));
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResponseEntity<ResponseData> testTran(int id) throws Exception {
        try {
            // 数据库操作
            this.delete(id);
            throw new Exception("测试事务的异常");
        } catch (Exception err) {
            System.out.println("出现了异常, 事务回滚: " + err.getMessage());
            // 如果异常被 try/catch 吞了是不会回滚的，所以这里手动抛出去
            throw err;
        }
    }
}
